home *** CD-ROM | disk | FTP | other *** search
/ Personal Computer World 2005 October / PCWOCT05.iso / Software / FromTheMag / XAMPP 1.4.14 / xampp-win32-1.4.14-installer.exe / xampp / php / pear / Math / Stats.php < prev    next >
PHP Script  |  2004-03-24  |  29KB  |  882 lines

  1. <?php
  2. //
  3. // +----------------------------------------------------------------------+
  4. // | PHP Version 4                                                        |
  5. // +----------------------------------------------------------------------+
  6. // | Copyright (c) 1997-2003 The PHP Group                                |
  7. // +----------------------------------------------------------------------+
  8. // | This source file is subject to version 2.0 of the PHP license,       |
  9. // | that is bundled with this package in the file LICENSE, and is        |
  10. // | available at through the world-wide-web at                           |
  11. // | http://www.php.net/license/2_02.txt.                                 |
  12. // | If you did not receive a copy of the PHP license and are unable to   |
  13. // | obtain it through the world-wide-web, please send a note to          |
  14. // | license@php.net so we can mail you a copy immediately.               |
  15. // +----------------------------------------------------------------------+
  16. // | Authors: Jesus M. Castagnetto <jmcastagnetto@php.net>                |
  17. // +----------------------------------------------------------------------+
  18. //
  19. // $Id: Stats.php,v 1.10 2003/05/16 22:03:03 jmcastagnetto Exp $
  20. //
  21.  
  22. include_once "PEAR.php";
  23.  
  24. /**
  25.  * @package Math_Stats
  26.  */
  27.  
  28. // Constants for defining the statistics to calculate /*{{{*/
  29. /**
  30.  * STATS_BASIC to generate the basic descriptive statistics
  31.  */
  32. define("STATS_BASIC", 1);
  33. /**
  34.  * STATS_FULL to generate also higher moments, mode, median, etc.
  35.  */
  36. define("STATS_FULL", 2);
  37. /*}}}*/
  38.  
  39. // Constants describing the data set format /*{{{*/
  40. /**
  41.  * STATS_DATA_SIMPLE for an array of numeric values
  42.  * e.g. $data = array(2,3,4,5,1,1,6);
  43.  */
  44. define("STATS_DATA_SIMPLE", 0);
  45. /**
  46.  * STATS_DATA_CUMMULATIVE for an associative array of frequency values,
  47.  * where in each array entry, the index is the data point and the
  48.  * value the count (frequency):
  49.  * e.g. $data = array(3=>4, 2.3=>5, 1.25=>6, 0.5=>3)
  50.  */
  51. define("STATS_DATA_CUMMULATIVE", 1);
  52. /*}}}*/
  53.  
  54. // Constants defining how to handle nulls /*{{{*/
  55. /**
  56.  * STATS_REJECT_NULL, reject data sets with null values.
  57.  * Any non-numeric value is considered a null in this context.
  58.  */
  59. define("STATS_REJECT_NULL", -1);
  60. /**
  61.  * STATS_IGNORE_NULL, ignore null values and prune them from the data.
  62.  * Any non-numeric value is considered a null in this context.
  63.  */
  64. define("STATS_IGNORE_NULL", -2);
  65. /**
  66.  * STATS_USE_NULL_AS_ZERO, assign the value of 0 (zero) to null values.
  67.  * Any non-numeric value is considered a null in this context.
  68.  */
  69. define("STATS_USE_NULL_AS_ZERO", -3);
  70. /*}}}*/
  71.  
  72. /**
  73.  * A class to calculate descriptive statistics from a data set.
  74.  * Data sets can be simple arrays of data, or a cummulative hash.
  75.  * The second form is useful when passing large data set,
  76.  * for example the data set:
  77.  *
  78.  * <pre>
  79.  * $data1 = array (1,2,1,1,1,1,3,3,4.1,3,2,2,4.1,1,1,2,3,3,2,2,1,1,2,2);
  80.  * </pre>
  81.  *
  82.  * can be epxressed more compactly as:
  83.  *
  84.  * <pre>
  85.  * $data2 = array("1"=>9, "2"=>8, "3"=>5, "4.1"=>2);
  86.  * </pre>
  87.  *
  88.  * Example of use:
  89.  *
  90.  * <pre>
  91.  * include_once "Math/Stats.php";
  92.  * $s = new Math_Stats();
  93.  * $s->setData($data1);
  94.  * // or
  95.  * // $s->setData($data2, STATS_DATA_CUMMULATIVE);
  96.  * $stats = $s->calcBasic();
  97.  * echo "Mean: ".$stats["mean"]." StDev: ".$stats["stdev"]." <br />\n";
  98.  * 
  99.  * // using data with nulls
  100.  * // first ignoring them:
  101.  * $data3 = array(1.2, "foo", 2.4, 3.1, 4.2, 3.2, null, 5.1, 6.2);
  102.  * $s->setNullOption(STATS_IGNORE_NULL);
  103.  * $s->setData($data3);
  104.  * $stats3 = $s->calcFull();
  105.  *
  106.  * // and then assuming nulls == 0
  107.  * $s->setNullOption(STATS_USE_NULL_AS_ZERO);
  108.  * $s->setData($data3);
  109.  * $stats3 = $s->calcFull();
  110.  * </pre>
  111.  *
  112.  * Originally this class was part of NumPHP (Numeric PHP package)
  113.  *
  114.  * @author  Jesus M. Castagnetto <jmcastagnetto@php.net>
  115.  * @version 0.8
  116.  * @access  public
  117.  * @package Math_Stats
  118.  */
  119. class Math_Stats {/*{{{*/
  120.     // properties /*{{{*/
  121.     
  122.     /**
  123.      * The simple or cummulative data set.
  124.      * Null by default.
  125.      *
  126.      * @access  private
  127.      * @var array
  128.      */
  129.     var $_data = null;
  130.  
  131.     /**
  132.      * Flag for data type, one of STATS_DATA_SIMPLE or
  133.      * STATS_DATA_CUMMULATIVE. Null by default.
  134.      *
  135.      * @access  private
  136.      * @var int
  137.      */
  138.     var $_dataOption = null;
  139.  
  140.     /**
  141.      * Flag for null handling options. One of STATS_REJECT_NULL,
  142.      * STATS_IGNORE_NULL or STATS_USE_NULL_AS_ZERO
  143.      *
  144.      * @access  private
  145.      * @var int
  146.      */
  147.     var $_nullOption;
  148.  
  149.     /*}}}*/
  150.     
  151.     /**
  152.      * Constructor for the class
  153.      *
  154.      * @access  public
  155.      * @param   optional    int $nullOption how to handle null values
  156.      * @return  object  Math_Stats
  157.      */
  158.     function Math_Stats($nullOption=STATS_REJECT_NULL) {/*{{{*/
  159.         $this->_nullOption = $nullOption;
  160.     }/*}}}*/
  161.  
  162.     /**
  163.      * Sets and verifies the data, checking for nulls and using
  164.      * the current null handling option
  165.      *
  166.      * @access public
  167.      * @param   array   $arr    the data set
  168.      * @param   optional    int $opt    data format: STATS_DATA_CUMMULATIVE or STATS_DATA_SIMPLE (default)
  169.      * @return  mixed   true on success, a PEAR_Error object otherwise
  170.      */
  171.     function setData($arr, $opt=STATS_DATA_SIMPLE) {/*{{{*/
  172.         $this->_data = null;
  173.         $this->_dataOption = null;
  174.         if (!is_array($arr))
  175.             return PEAR::raiseError("invalid data, an array of numeric data was expected");
  176.         if ($opt == STATS_DATA_SIMPLE) {
  177.             $this->_dataOption = $opt;
  178.             $this->_data = array_values($arr);
  179.         } else if ($opt == STATS_DATA_CUMMULATIVE) {
  180.             $this->_dataOption = $opt;
  181.             $this->_data = $arr;
  182.         } 
  183.         return $this->_validate();
  184.     }/*}}}*/
  185.  
  186.     /**
  187.      * Returns the data which might have been modified
  188.      * according to the current null handling options.
  189.      *
  190.      * @access  public
  191.      * @return  mixed   array of data on success, a PEAR_Error object otherwise
  192.      * @see _validate()
  193.      */
  194.     function getData() {/*{{{*/
  195.         if ($this->_data == null)
  196.             return PEAR::raiseError("data has not been set");
  197.         return $this->_data;
  198.     }/*}}}*/
  199.  
  200.     /**
  201.      * Sets the null handling option.
  202.      * Must be called before assigning a new data set containing null values
  203.      * 
  204.      * @access  public
  205.      * @return  mixed   true on success, a PEAR_Error object otherwise
  206.      * @see _validate()
  207.      */
  208.     function setNullOption($nullOption) {/*{{{*/
  209.         if ($nullOption == STATS_REJECT_NULL
  210.             || $nullOption == STATS_IGNORE_NULL
  211.             || $nullOption == STATS_USE_NULL_AS_ZERO) {
  212.             $this->_nullOption = $nullOption;
  213.             return true;
  214.         } else {
  215.             return PEAR::raiseError("invalid null handling option expecting: ".
  216.                         "STATS_REJECT_NULL, STATS_IGNORE_NULL or STATS_USE_NULL_AS_ZERO");
  217.         }
  218.     }/*}}}*/
  219.  
  220.     /**
  221.      * Calculates the basic or full statistics for the data set
  222.      * 
  223.      * @access  public
  224.      * @param   int $mode   one of STATS_BASIC or STATS_FULL
  225.      * @return  mixed   an associative array of statistics on success, a PEAR_Error object otherwise
  226.      * @see calcBasic()
  227.      * @see calcFull()
  228.      */ 
  229.     function calc($mode) {/*{{{*/
  230.         if ($this->_data == null)
  231.             return PEAR::raiseError("data has not been set");
  232.         if ($mode == STATS_BASIC) {
  233.             return array (
  234.                 "min" => $this->min(),
  235.                 "max" => $this->max(),
  236.                 "sum" => $this->sum(),
  237.                 "sum2" => $this->sum2(),
  238.                 "count" => $this->count(),
  239.                 "mean" => $this->mean(),
  240.                 "stdev" => $this->stDev(),
  241.                 "variance" => $this->variance()
  242.             );
  243.         } else if ($mode == STATS_FULL) {
  244.             return array (
  245.                 "min" => $this->min(),
  246.                 "max" => $this->max(),
  247.                 "sum" => $this->sum(),
  248.                 "sum2" => $this->sum2(),
  249.                 "count" => $this->count(),
  250.                 "mean" => $this->mean(),
  251.                 "median" => $this->median(),
  252.                 "mode" => $this->mode(),
  253.                 "midrange" => $this->midrange(),
  254.                 "stdev" => $this->stDev(),
  255.                 "absdev" => $this->absDev(),
  256.                 "variance" => $this->variance(),
  257.                 "std_error_of_mean" => $this->stdErrorOfMean(),
  258.                 "skewness" => $this->skewness(),
  259.                 "kurtosis" => $this->kurtosis(),
  260.                 "coeff_of_variation" => $this->coeffOfVariation(),
  261.                 "sample_central_moments" => array (
  262.                             1 => $this->sampleCentralMoment(1),
  263.                             2 => $this->sampleCentralMoment(2),
  264.                             3 => $this->sampleCentralMoment(3),
  265.                             4 => $this->sampleCentralMoment(4),
  266.                             5 => $this->sampleCentralMoment(5)
  267.                             ),
  268.                 "sample_raw_moments" => array (
  269.                             1 => $this->sampleRawMoment(1),
  270.                             2 => $this->sampleRawMoment(2),
  271.                             3 => $this->sampleRawMoment(3),
  272.                             4 => $this->sampleRawMoment(4),
  273.                             5 => $this->sampleRawMoment(5)
  274.                             ),
  275.                 "frequency" => $this->frequency()
  276.             );
  277.         } else {
  278.             return PEAR::raiseError("incorrect mode, expected STATS_BASIC or STATS_FULL");
  279.         }
  280.     }/*}}}*/
  281.  
  282.     /**
  283.      * Calculates a basic set of statistics
  284.      *
  285.      * @access  public
  286.      * @return  mixed   an associative array of statistics on success, a PEAR_Error object otherwise
  287.      * @see calc()
  288.      * @see calcFull()
  289.      */
  290.     function calcBasic() {/*{{{*/
  291.         return $this->calc(STATS_BASIC);
  292.     }/*}}}*/
  293.  
  294.     /**
  295.      * Calculates a full set of statistics
  296.      *
  297.      * @access  public
  298.      * @return  mixed   an associative array of statistics on success, a PEAR_Error object otherwise
  299.      * @see calc()
  300.      * @see calcBasic()
  301.      */
  302.     function calcFull() {/*{{{*/
  303.         return $this->calc(STATS_FULL);
  304.     }/*}}}*/
  305.  
  306.     /**
  307.      * Calculates the minimum of a data set.
  308.      * Handles cummulative data sets correctly
  309.      *
  310.      * @access  public
  311.      * @return  mixed   the minimum value on success, a PEAR_Error object otherwise
  312.      * @see calc()
  313.      * @see max()
  314.      */
  315.     function min() {/*{{{*/
  316.         if ($this->_data == null)
  317.             return PEAR::raiseError("data has not been set");
  318.         if ($this->_dataOption == STATS_DATA_CUMMULATIVE)
  319.             return min(array_keys($this->_data));
  320.         else
  321.             return min($this->_data);
  322.     }/*}}}*/
  323.  
  324.     /**
  325.      * Calculates the maximum of a data set.
  326.      * Handles cummulative data sets correctly
  327.      *
  328.      * @access  public
  329.      * @return  mixed   the maximum value on success, a PEAR_Error object otherwise
  330.      * @see calc()
  331.      * @see min()
  332.      */
  333.     function max() {/*{{{*/
  334.         if ($this->_data == null)
  335.             return PEAR::raiseError("data has not been set");
  336.         if ($this->_dataOption == STATS_DATA_CUMMULATIVE)
  337.             return max(array_keys($this->_data));
  338.         else
  339.             return max($this->_data);
  340.     }/*}}}*/
  341.  
  342.     /**
  343.      * Calculates SUM { xi }
  344.      * Handles cummulative data sets correctly
  345.      *
  346.      * @access  public
  347.      * @return  mixed   the sum on success, a PEAR_Error object otherwise   
  348.      * @see calc()
  349.      * @see sum2()
  350.      * @see sumN()
  351.      */
  352.     function sum() {/*{{{*/
  353.         return $this->sumN(1);
  354.     }/*}}}*/
  355.  
  356.     /**
  357.      * Calculates SUM { (xi)^2 }
  358.      * Handles cummulative data sets correctly
  359.      *
  360.      * @access  public
  361.      * @return  mixed   the sum on success, a PEAR_Error object otherwise   
  362.      * @see calc()
  363.      * @see sum()
  364.      * @see sumN()
  365.      */
  366.     function sum2() {/*{{{*/
  367.         return $this->sumN(2);
  368.     }/*}}}*/
  369.  
  370.     /**
  371.      * Calculates SUM { (xi)^n }
  372.      * Handles cummulative data sets correctly
  373.      *
  374.      * @access  public
  375.      * @param   numeric $n  the exponent
  376.      * @return  mixed   the sum on success, a PEAR_Error object otherwise   
  377.      * @see calc()
  378.      * @see sum()
  379.      * @see sum2()
  380.      */
  381.     function sumN($n) {/*{{{*/
  382.         if ($this->_data == null)
  383.             return PEAR::raiseError("data has not been set");
  384.         $sumN = 0;
  385.         if ($this->_dataOption == STATS_DATA_CUMMULATIVE) {
  386.             foreach($this->_data as $val=>$freq)
  387.                 $sumN += $freq * pow((double)$val, (double)$n);
  388.         } else {
  389.             foreach($this->_data as $val)
  390.                 $sumN += pow((double)$val, (double)$n);
  391.         }
  392.         return $sumN;
  393.     }/*}}}*/
  394.  
  395.     /**
  396.      * Calculates the number of data points in the set
  397.      * Handles cummulative data sets correctly
  398.      *
  399.      * @access  public
  400.      * @return  mixed   the count on success, a PEAR_Error object otherwise 
  401.      * @see calc()
  402.      */
  403.     function count() {/*{{{*/
  404.         if ($this->_data == null)
  405.             return PEAR::raiseError("data has not been set");
  406.         if ($this->_dataOption == STATS_DATA_CUMMULATIVE) {
  407.             foreach($this->_data as $freq)
  408.                 $count += $freq;
  409.         } else {
  410.             $count = count($this->_data);
  411.         }
  412.         return $count;
  413.     }/*}}}*/
  414.  
  415.     /**
  416.      * Calculates the mean (average) of the data points in the set
  417.      * Handles cummulative data sets correctly
  418.      *
  419.      * @access  public
  420.      * @return  mixed   the mean value on success, a PEAR_Error object otherwise    
  421.      * @see calc()
  422.      * @see sum()
  423.      * @see count()
  424.      */
  425.     function mean() {/*{{{*/
  426.         if ($this->_data == null)
  427.             return PEAR::raiseError("data has not been set");
  428.         return ($this->sum() / $this->count());
  429.     }/*}}}*/
  430.  
  431.     /**
  432.      * Calculates the variance (unbiased) of the data points in the set
  433.      * Handles cummulative data sets correctly
  434.      *
  435.      * @access  public
  436.      * @return  mixed   the variance value on success, a PEAR_Error object otherwise    
  437.      * @see calc()
  438.      * @see __sumdiff()
  439.      * @see count()
  440.      */
  441.     function variance() {/*{{{*/
  442.         if ($this->_data == null)
  443.             return PEAR::raiseError("data has not been set");
  444.         return $this->__sumdiff(2) / ($this->count() - 1);
  445.     }/*}}}*/
  446.  
  447.     /**
  448.      * Calculates the standard deviation (unbiased) of the data points in the set
  449.      * Handles cummulative data sets correctly
  450.      *
  451.      * @access  public
  452.      * @return  mixed   the standard deviation on success, a PEAR_Error object otherwise    
  453.      * @see calc()
  454.      * @see variance()
  455.      */
  456.     function stDev() {/*{{{*/
  457.         if ($this->_data == null)
  458.             return PEAR::raiseError("data has not been set");
  459.         return sqrt($this->variance());
  460.     }/*}}}*/
  461.  
  462.     /**
  463.      * Calculates the variance (unbiased) of the data points in the set
  464.      * given a fixed mean (average) value. Not used in calcBasic(), calcFull()
  465.      * or calc().
  466.      * Handles cummulative data sets correctly
  467.      *
  468.      * @access  public
  469.      * @param   numeric $mean   the fixed mean value
  470.      * @return  mixed   the variance on success, a PEAR_Error object otherwise  
  471.      * @see __sumdiff()
  472.      * @see count()
  473.      * @see variance()
  474.      */
  475.     function varianceWithMean($mean) {/*{{{*/
  476.         if ($this->_data == null)
  477.             return PEAR::raiseError("data has not been set");
  478.         return $this->__sumdiff(2, $mean) / ($this->count() - 1);
  479.     }/*}}}*/
  480.     
  481.     /**
  482.      * Calculates the standard deviation (unbiased) of the data points in the set
  483.      * given a fixed mean (average) value. Not used in calcBasic(), calcFull()
  484.      * or calc().
  485.      * Handles cummulative data sets correctly
  486.      *
  487.      * @access  public
  488.      * @param   numeric $mean   the fixed mean value
  489.      * @return  mixed   the standard deviation on success, a PEAR_Error object otherwise    
  490.      * @see varianceWithMean()
  491.      * @see stDev()
  492.      */
  493.     function stDevWithMean($mean) {/*{{{*/
  494.         if ($this->_data == null)
  495.             return PEAR::raiseError("data has not been set");
  496.         return sqrt($this->varianceWithMean($mean));
  497.     }/*}}}*/
  498.  
  499.     /**
  500.      * Calculates the absolute deviation of the data points in the set
  501.      * Handles cummulative data sets correctly
  502.      *
  503.      * @access  public
  504.      * @return  mixed   the absolute deviation on success, a PEAR_Error object otherwise    
  505.      * @see calc()
  506.      * @see __sumabsdev()
  507.      * @see count()
  508.      * @see absDevWithMean()
  509.      */
  510.     function absDev() {/*{{{*/
  511.         if ($this->_data == null)
  512.             return PEAR::raiseError("data has not been set");
  513.         return $this->__sumabsdev() / $this->count();
  514.     }/*}}}*/
  515.  
  516.     /**
  517.      * Calculates the absolute deviation of the data points in the set
  518.      * given a fixed mean (average) value. Not used in calcBasic(), calcFull()
  519.      * or calc().
  520.      * Handles cummulative data sets correctly
  521.      *
  522.      * @access  public
  523.      * @param   numeric $mean   the fixed mean value
  524.      * @return  mixed   the absolute deviation on success, a PEAR_Error object otherwise    
  525.      * @see __sumabsdev()
  526.      * @see absDev()
  527.      */
  528.     function absDevWithMean($mean) {/*{{{*/
  529.         if ($this->_data == null)
  530.             return PEAR::raiseError("data has not been set");
  531.         return $this->__sumabsdev($mean) / $this->count();
  532.     }/*}}}*/
  533.  
  534.     /**
  535.      * Calculates the skewness of the data distribution in the set
  536.      * The skewness measures the degree of asymmetry of a distribution,
  537.      * and is related to the third central moment of a distribution.
  538.      * A normal distribution has a skewness = 0
  539.      * A distribution with a tail off towards the high end of the scale
  540.      * (positive skew) has a skewness > 0
  541.      * A distribution with a tail off towards the low end of the scale
  542.      * (negative skew) has a skewness < 0
  543.      * Handles cummulative data sets correctly
  544.      *
  545.      * @access  public
  546.      * @return  mixed   the skewness value on success, a PEAR_Error object otherwise    
  547.      * @see __sumdiff()
  548.      * @see count()
  549.      * @see stDev()
  550.      * @see calc()
  551.      */
  552.     function skewness() {/*{{{*/
  553.         if ($this->_data == null)
  554.             return PEAR::raiseError("data has not been set");
  555.         $skew = ($this->__sumdiff(3) / ($this->count() * pow($this->stDev(), 3)));
  556.         return $skew;
  557.     }/*}}}*/
  558.  
  559.     /**
  560.      * Calculates the kurtosis of the data distribution in the set
  561.      * The kurtosis measures the degrees of peakedness of a distribution.
  562.      * It is also callesd the "excess" or "excess coefficient", and is
  563.      * a normalized form of the fourth central moment of a distribution.
  564.      * A normal distributions has kurtosis = 0
  565.      * A narrow and peaked (leptokurtic) distribution has a
  566.      * kurtosis > 0
  567.      * A flat and wide (platykurtic) distribution has a kurtosis < 0
  568.      * Handles cummulative data sets correctly
  569.      *
  570.      * @access  public
  571.      * @return  mixed   the kurtosis value on success, a PEAR_Error object otherwise    
  572.      * @see __sumdiff()
  573.      * @see count()
  574.      * @see stDev()
  575.      * @see calc()
  576.      */
  577.     function kurtosis() {/*{{{*/
  578.         if ($this->_data == null)
  579.             return PEAR::raiseError("data has not been set");
  580.         $kurt = ($this->__sumdiff(4) / ($this->count() * pow($this->stDev(), 4))) - 3;
  581.         return $kurt;
  582.     }/*}}}*/
  583.  
  584.     /**
  585.      * Calculates the median of a data set.
  586.      * The median is the value such that half of the points are below it
  587.      * in a sorted data set.
  588.      * If the number of values is odd, it is the middle item.
  589.      * If the number of values is even, is the average of the two middle items.
  590.      * Handles cummulative data sets correctly
  591.      *
  592.      * @access  public
  593.      * @return  mixed   the median value on success, a PEAR_Error object otherwise  
  594.      * @see count()
  595.      * @see calc()
  596.      */
  597.     function median() {/*{{{*/
  598.         if ($this->_data == null)
  599.             return PEAR::raiseError("data has not been set");
  600.         $arr = array();
  601.         if ($this->_dataOption == STATS_DATA_CUMMULATIVE)
  602.             foreach ($this->_data as $val=>$freq)
  603.                 $arr = array_pad($arr, count($arr) + $freq, $val);
  604.         else
  605.             $arr = $this->_data;
  606.         sort($arr);
  607.         $n = count($arr);
  608.         $h = intval($n / 2);
  609.         if ($n % 2 == 0) {
  610.             $median = ($arr[$h] + $arr[$h - 1]) / 2;
  611.         } else {
  612.             $median = $arr[$h + 1];
  613.         }
  614.         return $median;
  615.     }/*}}}*/
  616.  
  617.     /**
  618.      * Calculates the mode of a data set.
  619.      * The mode is the value with the highest frequency in the data set.
  620.      * There can be more than one mode.
  621.      * Handles cummulative data sets correctly
  622.      *
  623.      * @access  public
  624.      * @return  mixed   an array of mode value on success, a PEAR_Error object otherwise    
  625.      * @see frequency()
  626.      * @see calc()
  627.      */
  628.     function mode() {/*{{{*/
  629.         if ($this->_data == null)
  630.             return PEAR::raiseError("data has not been set");
  631.         if ($this->_dataOption == STATS_DATA_CUMMULATIVE)
  632.             $arr = $this->_data;
  633.         else
  634.             $arr = $this->frequency();
  635.         arsort($arr);
  636.         $mcount = 1;
  637.         foreach ($arr as $val=>$freq) {
  638.             if ($mcount == 1) {
  639.                 $mode = array($val);
  640.                 $mfreq = $freq;
  641.                 $mcount++;
  642.                 continue;
  643.             }
  644.             if ($mfreq == $freq)
  645.                 $mode[] = $val;
  646.             if ($mfreq > $freq)
  647.                 break;
  648.         }
  649.         return $mode;
  650.     }/*}}}*/
  651.  
  652.     /**
  653.      * Calculates the nth central moment (m{n}) of a data set.
  654.      *
  655.      * The definition of a sample central moment is:
  656.      *
  657.      *     m{n} = 1/N * SUM { (xi - avg)^n }
  658.      *
  659.      * where: N = sample size, avg = sample mean.
  660.      */
  661.     function sampleCentralMoment($n) {/*{{{*/
  662.         if ($n == 1) {
  663.             return 0;
  664.         }
  665.         $count = $this->count();
  666.         if (PEAR::isError($count)) {
  667.             return $count;
  668.         }
  669.         if ($count == 0) {
  670.             return PEAR::raiseError("Cannot calculate {$n}th sample moment, there are zero data entries.");
  671.         }
  672.         $sum = $this->__sumdiff($n);
  673.         if (PEAR::isError($sum)) {
  674.             return $sum;
  675.         }
  676.         return ($sum / $count);
  677.     }/*}}}*/
  678.  
  679.     /**
  680.      * Calculates the nth raw moment (m{n}) of a data set.
  681.      *
  682.      * The definition of a sample central moment is:
  683.      *
  684.      *     m{n} = 1/N * SUM { xi^n }
  685.      *
  686.      * where: N = sample size, avg = sample mean.
  687.      */
  688.     function sampleRawMoment($n) {/*{{{*/
  689.         $count = $this->count();
  690.         if (PEAR::isError($count)) {
  691.             return $count;
  692.         }
  693.         if ($count == 0) {
  694.             return PEAR::raiseError("Cannot calculate {$n}th raw moment, there are zero data entries.");
  695.         }
  696.         $sum = $this->sumN($n);
  697.         if (PEAR::isError($sum)) {
  698.             return $sum;
  699.         }
  700.         return ($sum / $count);
  701.     }/*}}}*/
  702.  
  703.     /**
  704.      * Calculates the midrange of a data set.
  705.      * The midrange is the average of the minimum and maximum of the data set.
  706.      * Handles cummulative data sets correctly
  707.      *
  708.      * @access  public
  709.      * @return  mixed   the midrange value on success, a PEAR_Error object otherwise    
  710.      * @see min()
  711.      * @see max()
  712.      * @see calc()
  713.      */
  714.     function midrange() {/*{{{*/
  715.         if ($this->_data == null)
  716.             return PEAR::raiseError("data has not been set");
  717.         return (($this->max() + $this->min()) / 2);
  718.     }/*}}}*/
  719.  
  720.     /**
  721.      * Calculates the value frequency table of a data set.
  722.      * Handles cummulative data sets correctly
  723.      *
  724.      * @access  public
  725.      * @return  mixed   an associative array of value=>frequency items on success, a PEAR_Error object otherwise    
  726.      * @see min()
  727.      * @see max()
  728.      * @see calc()
  729.      */
  730.     function frequency() {/*{{{*/
  731.         if ($this->_data == null)
  732.             return PEAR::raiseError("data has not been set");
  733.         if ($this->_dataOption == STATS_DATA_CUMMULATIVE) {
  734.             return $this->_data;
  735.         } else {
  736.             $freq = array();
  737.             foreach ($this->_data as $val)
  738.                 $freq["$val"]++;
  739.             return $freq;
  740.         }
  741.     }/*}}}*/
  742.  
  743.     /**
  744.      * Calculates the coefficient of variation of a data set.
  745.      * The coefficient of variation measures the spread of a set of data 
  746.      * as a proportion of its mean. It is often expressed as a percentage.
  747.      * Handles cummulative data sets correctly
  748.      *
  749.      * @access  public
  750.      * @return  mixed   the coefficient of variation on success, a PEAR_Error object otherwise  
  751.      * @see stDev()
  752.      * @see mean()
  753.      * @see calc()
  754.      */
  755.     function coeffOfVariation() {/*{{{*/
  756.         if ($this->_data == null)
  757.             return PEAR::raiseError("data has not been set");
  758.         return $this->stDev() / $this->mean();
  759.     }/*}}}*/
  760.  
  761.     /**
  762.      * Calculates the standard error of the mean.
  763.      * It is the standard deviation of the sampling distribution of
  764.      * the mean. The formula is:
  765.      *
  766.      * S.E. Mean = SD / (N)^(1/2)
  767.      *
  768.      * This formula does not assume a normal distribution, and shows
  769.      * that the size of the standard error of the mean is inversely
  770.      * proportional to the square root of the sample size. 
  771.      *
  772.      * @access  public
  773.      * @return  mixed   the standard error of the mean on success, a PEAR_Error object otherwise  
  774.      * @see stDev()
  775.      * @see count()
  776.      * @see calc()
  777.      */
  778.     function stdErrorOfMean() {/*{{{*/
  779.         if ($this->_data == null)
  780.             return PEAR::raiseError("data has not been set");
  781.         return $this->stDev() / sqrt($this->count());
  782.     }/*}}}*/
  783.  
  784.     /**
  785.      * Utility function to calculate: SUM { (xi - mean)^n }
  786.      * 
  787.      * @access private
  788.      * @param   numeric $power  the exponent
  789.      * @param   optional    double   $mean   the data set mean value
  790.      * @return  mixed   the sum on success, a PEAR_Error object otherwise
  791.      *
  792.      * @see stDev()
  793.      * @see variaceWithMean();
  794.      * @see skewness();
  795.      * @see kurtosis();
  796.      */
  797.     function __sumdiff($power, $mean=null) {/*{{{*/
  798.         if ($this->_data == null)
  799.             return PEAR::raiseError("data has not been set");
  800.         if (is_null($mean))
  801.             $mean = $this->mean();
  802.         $sdiff = 0;
  803.         if ($this->_dataOption == STATS_DATA_CUMMULATIVE) {
  804.             foreach ($this->_data as $val=>$freq)
  805.                 $sdiff += $freq * pow((double)($val - $mean), (double)$power);
  806.         } else {
  807.             foreach ($this->_data as $val)
  808.                 $sdiff += pow((double)($val - $mean), (double)$power);
  809.         }
  810.         return $sdiff;
  811.     }/*}}}*/
  812.  
  813.     /**
  814.      * Utility function to calculate: SUM { | xi - mean | }
  815.      *
  816.      * @access  private
  817.      * @param   optional    double   $mean   the mean value for the set or population
  818.      * @return  mixed   the sum on success, a PEAR_Error object otherwise
  819.      *
  820.      * @see absDev()
  821.      * @see absDevWithMean()
  822.      */
  823.     function __sumabsdev($mean=null) {/*{{{*/
  824.         if ($this->_data == null)
  825.             return PEAR::raiseError("data has not been set");
  826.         if (is_null($mean))
  827.             $mean = $this->mean();
  828.         $sdev = 0;
  829.         if ($this->_dataOption == STATS_DATA_CUMMULATIVE) {
  830.             foreach ($this->_data as $val=>$freq)
  831.                 $sdev += $freq * abs($val - $mean);
  832.         } else {
  833.             foreach ($this->_data as $val)
  834.                 $sdev += abs($val - $mean);
  835.         }
  836.         return $sdev;
  837.     }/*}}}*/
  838.  
  839.     /**
  840.      * Utility function to validate the data and modify it
  841.      * according to the current null handling option
  842.      *
  843.      * @access  private
  844.      * @return  mixed true on success, a PEAR_Error object otherwise
  845.      * 
  846.      * @see setData()
  847.      */
  848.     function _validate() {/*{{{*/
  849.         $flag = ($this->_dataOption == STATS_DATA_CUMMULATIVE);
  850.         foreach ($this->_data as $key=>$value) {
  851.             $d = ($flag) ? $key : $value;
  852.             $v = ($flag) ? $value : $key;
  853.             if (!is_numeric($d)) {
  854.                 switch ($this->_nullOption) {
  855.                     case STATS_IGNORE_NULL :
  856.                         unset($this->_data["$key"]);
  857.                         break;
  858.                     case STATS_USE_NULL_AS_ZERO:
  859.                         if ($flag) {
  860.                             unset($this->_data["$key"]);
  861.                             $this->_data[0] += $v;
  862.                         } else {
  863.                             $this->_data[$key] = 0;
  864.                         }
  865.                         break;
  866.                     case STATS_REJECT_NULL :
  867.                     default:
  868.                         return PEAR::raiseError("data rejected, contains NULL values");
  869.                         break;
  870.                 }
  871.             }
  872.         }
  873.         return true;
  874.     }/*}}}*/
  875.  
  876. }/*}}}*/
  877.  
  878. // vim: ts=4:sw=4:et:
  879. // vim6: fdl=0:
  880.  
  881. ?>
  882.